package main

import (
	"bufio"
	"fmt"
	"os"
)

/*
   bufio 是通过缓冲来提高效率。
     io操作本身的效率并不低，低的是频繁的访问本地磁盘的文件。
   所以bufio就提供了缓冲区(分配一块内存)，读和写都先在缓冲区中，最后再读写文件，来降低访问本地磁盘的次数，从而提高效率。


   bufio.Reader 是bufio中对io.Reader 的封装

   type Reader struct {
    buf          []byte
    rd           io.Reader // reader provided by the client
    r, w         int       // buf read and write positions
    err          error
    lastByte     int // last byte read for UnreadByte; -1 means invalid
    lastRuneSize int // size of last rune read for UnreadRune; -1 means invalid
   }

   bufio.Read(p []byte) 相当于读取大小len(p)的内容，思路如下：

   当缓存区有内容的时，将缓存区内容全部填入p并清空缓存区
   当缓存区没有内容的时候且len(p)>len(buf),即要读取的内容比缓存区还要大，直接去文件读取即可
   当缓存区没有内容的时候且len(p)<len(buf),即要读取的内容比缓存区小，缓存区从文件读取内容充满缓存区，并将p填满（此时缓存区有剩余内容）
   以后再次读取时缓存区有内容，将缓存区内容全部填入p并清空缓存区（此时和情况1一样）

   bufio.Writer 是bufio中对io.Writer 的封装
   type Writer struct {
    err error
    buf []byte
    n   int
    wr  io.Writer
  }

  bufio.Write(p []byte) 的思路如下

	判断buf中可用容量是否可以放下 p
	如果能放下，直接把p拼接到buf后面，即把内容放到缓冲区
	如果缓冲区的可用容量不足以放下，且此时缓冲区是空的，直接把p写入文件即可
	如果缓冲区的可用容量不足以放下，且此时缓冲区有内容，则用p把缓冲区填满，把缓冲区所有内容写入文件，并清空缓冲区
	判断p的剩余内容大小能否放到缓冲区，如果能放下（此时和步骤1情况一样）则把内容放到缓冲区
	如果p的剩余内容依旧大于缓冲区，（注意此时缓冲区是空的，情况和步骤3一样）则把p的剩余内容直接写入文件

*/
func main() {

	/*
	   bufio:高效io读写
	       buffer缓存
	       io：input/output

	   将io包下的Reader，Write对象进行包装，带缓存的包装，提高读写的效率

	       ReadBytes()
	       ReadString()
	       ReadLine()
	*/

	fileName :="/Users/chukun/work/other/a.txt"
	file,err := os.Open(fileName)
	if err != nil{
		fmt.Println(err)
		return
	}
	defer file.Close()

	//创建Reader对象
	b1 := bufio.NewReader(file)
	p := make([]byte,1024)
	n1,err := b1.Read(p)
	fmt.Println(n1)
	fmt.Println(string(p[:n1]))

	//2.ReadLine()
	data,flag,err := b1.ReadLine()
	fmt.Println(flag)
	fmt.Println(err)
	fmt.Println(data)
	fmt.Println(string(data))

	//3.ReadString()
	s1,err :=b1.ReadString('\n')
	fmt.Println(err)
	fmt.Println(s1)

	//4.ReadBytes()
	data02,err02 :=b1.ReadBytes('\n')
	fmt.Println(err02)
	fmt.Println(string(data02))

	//Scanner
	b2 := bufio.NewReader(os.Stdin)
	s2, _ := b2.ReadString('\n')
	fmt.Println(s2)

	/*
	   bufio:高效io读写
	       buffer缓存
	       io：input/output

	   将io包下的Reader，Write对象进行包装，带缓存的包装，提高读写的效率

	       func (b *Writer) Write(p []byte) (nn int, err error)
	       func (b *Writer) WriteByte(c byte) error
	       func (b *Writer) WriteRune(r rune) (size int, err error)
	       func (b *Writer) WriteString(s string) (int, error)
	*/

	fileName01 := "/Users/chukun/work/other/b.txt"
	file03, err03 := os.OpenFile(fileName01, os.O_CREATE|os.O_WRONLY, os.ModePerm)
	if err03 != nil{
		fmt.Println(err)
		return
	}
	defer file03.Close()

	writer:= bufio.NewWriter(file03)
	n,err := writer.WriteString("helloworld")
	fmt.Println(err)
	fmt.Println(n)
	_ = writer.Flush() //刷新缓冲区

}
